import pandas as pd
from scipy.io import arff
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report

"""
SFH（Server Form Handler）:

服务器表单处理程序的完整性。
通常取值范围为0, 1, 2：
0：空或错误的SFH，表明该信息可能发送到外部域名。
1：可疑的SFH，表明该信息可能发送到某个可疑的域名。
2：合法的SFH，表明该信息发送到合法的域名或没有表单处理程序。

popUpWindow:
弹出窗口的情况。
通常取值范围为0或1：
0：没有弹出窗口。
1：有弹出窗口。

SSLfinal_State:
SSL（安全套接层）/TLS状态。
通常取值范围为0, 1, 2：
0：无SSL证书或证书不可靠。
1：SSL存在，但不信任或者过期。
2：有效且高信任度SSL证书。


Request_URL:
URL请求的完整性。
通常取值范围为0, 1：
0：大多数请求的URL指向其他域名。
1：大多数请求的URL指向同一域名。


URL_of_Anchor:
锚点URL的完整性。
通常取值范围为0, 1，2：
0：大多数锚点指向外部域名。
1：大多数锚点指向可疑或错误的域名。
2：大多数锚点指向同一域名。


web_traffic:
网站的流量。
通常取值范围为0, 1，2：
0：非常低流量或没有流量。
1：适中的流量。
2：高流量。

URL_Length:
URL的长度。
通常根据实际情况设定阈值，数值越大表示URL越长。较长的URL可能更可疑。

age_of_domain:
域名的年龄。
通常以天数表示。数值越大表示域名存在的时间越长，较新的域名往往更可疑。

having_IP_Address:
URL中是否包含IP地址。
通常取值范围为0或1：
0：URL中不包含IP地址。
1：URL中包含IP地址（包含IP地址的URL可能更可疑）"""

import pandas as pd
from scipy.io import arff
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report

# 读取 arff 文件
data, meta = arff.loadarff('PhishingData.arff')

# 将数据转换为 DataFrame
df = pd.DataFrame(data)
# 数据数量
print(df.shape)

# 转换目标变量
df['Result'] = df['Result'].astype(int)

# 确保特征名称一致
df.rename(columns={'popUpWidnow': 'popUpWindow'}, inplace=True)

# 特征变量和目标变量
X = df.drop('Result', axis=1)
y = df['Result']

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 1. 随机森林
rf = RandomForestClassifier(random_state=42)
rf.fit(X_train, y_train)
rf_pred = rf.predict(X_test)

# 2. 逻辑回归
lr = LogisticRegression(max_iter=1000)
lr.fit(X_train, y_train)
lr_pred = lr.predict(X_test)

# 3. 支持向量机
svm = SVC()
svm.fit(X_train, y_train)
svm_pred = svm.predict(X_test)

# 4. 梯度提升
gb = GradientBoostingClassifier(random_state=42)
gb.fit(X_train, y_train)
gb_pred = gb.predict(X_test)

# 评估模型性能
models = {'Random Forest': rf_pred, 'Logistic Regression': lr_pred, 'SVM': svm_pred, 'Gradient Boosting': gb_pred}

for model_name, predictions in models.items():
    print(f"------ {model_name} ------")
    print("Accuracy:", accuracy_score(y_test, predictions))
    print("Classification Report:")
    print(classification_report(y_test, predictions))
    print("\n")

# 创建一个新的实例（确保特征名称一致）
new_instance = {
    'SFH': [0],
    'popUpWindow': [0],
    'SSLfinal_State': [0],
    'Request_URL': [0],
    'URL_of_Anchor': [0],
    'web_traffic': [1],
    'URL_Length': [10],
    'age_of_domain': [1],
    'having_IP_Address': [0]
}

new_instance_df = pd.DataFrame(new_instance)

# 用训练好的模型对新实例进行预测
rf_pred_instance = rf.predict(new_instance_df)
lr_pred_instance = lr.predict(new_instance_df)
svm_pred_instance = svm.predict(new_instance_df)
gb_pred_instance = gb.predict(new_instance_df)

# -1 表示“钓鱼网站”，而 0 表示“正常网站”，那么可理解为大多数模型（随机森林、SVM和梯度提升）预测这是一个钓鱼网站，而逻辑回归模型预测这是一个正常网站。

# 输出预测结果
print("------  Predictions for New Instance  ------")
print(f"Random Forest Prediction: {rf_pred_instance[0]}")
print(f"Logistic Regression Prediction: {lr_pred_instance[0]}")
print(f"SVM Prediction: {svm_pred_instance[0]}")
print(f"Gradient Boosting Prediction: {gb_pred_instance[0]}")
